// ==============================================================================================
// ╦  ┬┌─┐┌─┐┌┐┌┌─┐┌─┐    Yaksha Programming Language
// ║  ││  ├┤ │││└─┐├┤     is Licensed with GPLv3 + extra terms. Please see below.
// ╩═╝┴└─┘└─┘┘└┘└─┘└─┘
// Note: libs - MIT license, runtime/3rd - various
// ==============================================================================================
// GPLv3:
//
// Yaksha - Programming Language.
// Copyright (C) 2020 - 2024 Bhathiya Perera
//
// This program is free software: you can redistribute it and/or modify it under the terms
// of the GNU General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program.
// If not, see https://www.gnu.org/licenses/.
//
// ==============================================================================================
// Additional Terms:
//
// Please note that any commercial use of the programming language's compiler source code
// (everything except compiler/runtime, compiler/libs and compiler/3rd) require a written agreement
// with author of the language (Bhathiya Perera).
//
// If you are using it for an open source project, please give credits.
// Your own project must use GPLv3 license with these additional terms.
//
// You may use programs written in Yaksha/YakshaLisp for any legal purpose
// (commercial, open-source, closed-source, etc) as long as it agrees
// to the licenses of linked runtime libraries (see compiler/runtime/README.md).
//
// ==============================================================================================
// ic_token.h
// generated by ic_update_tokens.py
#ifndef IC_TOKEN_H
#define IC_TOKEN_H
#include <filesystem>
#include <string>
#include <vector>
namespace yaksha {
  /**
 * Most simple types of tokens we can match with tokenizing
 */
  enum class ic_token_type {
    ADD,
    ADD_ASSIGN,
    AMPERSAND,
    AND_ASSIGN,
    AND_OP,
    BACKSLASH,
    BITWISE_NOT,
    BOOL_NOT,
    CLOSE_BRACKET,
    CLOSE_CURLY,
    CLOSE_PAREN,
    COLON,
    COMMA,
    COMMENT,
    DEC_OP,
    DIV,
    DIV_ASSIGN,
    DOT,
    ELLIPSIS,
    ENUMERATION_CONSTANT,
    EQ,
    EQ_OP,
    FLOAT_CONSTANT,
    GE_OP,
    GREATER,
    HASH,
    HASH_HASH,
    IDENTIFIER,
    INC_OP,
    INTEGER_CONSTANT,
    LEFT_ASSIGN,
    LEFT_OP,
    LESS,
    LE_OP,
    MOD,
    MOD_ASSIGN,
    MUL,
    MULTILINE_COMMENT,
    MUL_ASSIGN,
    NEWLINE,
    NE_OP,
    NON_IDENTIFIER,
    OPEN_BRACKET,
    OPEN_CURLY,
    OPEN_PAREN,
    OR,
    OR_ASSIGN,
    OR_OP,
    PP_CONCAT,
    PP_DEFINE,
    PP_DEFINED,
    PP_DUNDER_FILE,
    PP_DUNDER_LINE,
    PP_DUNDER_VARARGS,
    PP_ELIF,
    PP_ELSE,
    PP_ENDIF,
    PP_ERROR,
    PP_IF,
    PP_IF_DEF,
    PP_IF_N_DEF,
    PP_INCLUDE,
    PP_LINE,
    PP_PRAGMA,
    PP_STRINGIFY,
    PP_UNDEF,
    PP_WARN,
    PTR_OP,
    QUESTION,
    RIGHT_ASSIGN,
    RIGHT_OP,
    SEMICOLON,
    STRING_LITERAL,
    SUB,
    SUB_ASSIGN,
    TC_EOF,
    TYPEDEF_NAME,
    XOR,
    XOR_ASSIGN,
    KEYWORD_ALIGNAS,
    KEYWORD_ALIGNOF,
    KEYWORD_ATOMIC,
    KEYWORD_BOOL,
    KEYWORD_COMPLEX,
    KEYWORD_GENERIC,
    KEYWORD_IMAGINARY,
    KEYWORD_NORETURN,
    KEYWORD_STATICASSERT,
    KEYWORD_THREADLOCAL,
    KEYWORD_FUNC,
    KEYWORD_AUTO,
    KEYWORD_BREAK,
    KEYWORD_CASE,
    KEYWORD_CHAR,
    KEYWORD_CONST,
    KEYWORD_CONTINUE,
    KEYWORD_DEFAULT,
    KEYWORD_DO,
    KEYWORD_DOUBLE,
    KEYWORD_ELSE,
    KEYWORD_ENUM,
    KEYWORD_EXTERN,
    KEYWORD_FLOAT,
    KEYWORD_FOR,
    KEYWORD_GOTO,
    KEYWORD_IF,
    KEYWORD_INLINE,
    KEYWORD_INT,
    KEYWORD_LONG,
    KEYWORD_REGISTER,
    KEYWORD_RESTRICT,
    KEYWORD_RETURN,
    KEYWORD_SHORT,
    KEYWORD_SIGNED,
    KEYWORD_SIZEOF,
    KEYWORD_STATIC,
    KEYWORD_STRUCT,
    KEYWORD_SWITCH,
    KEYWORD_TYPEDEF,
    KEYWORD_UNION,
    KEYWORD_UNSIGNED,
    KEYWORD_VOID,
    KEYWORD_VOLATILE,
    KEYWORD_WHILE,
    TK_UNKNOWN_TOKEN_DETECTED
  };
  /**
 * Convert a token to a string
 * @param t token type
 * @return token type as a std::string
 */
  static inline std::string ic_token_to_str(const ic_token_type &t) {
    if (t == ic_token_type::ADD) return "ADD";
    if (t == ic_token_type::ADD_ASSIGN) return "ADD_ASSIGN";
    if (t == ic_token_type::AMPERSAND) return "AMPERSAND";
    if (t == ic_token_type::AND_ASSIGN) return "AND_ASSIGN";
    if (t == ic_token_type::AND_OP) return "AND_OP";
    if (t == ic_token_type::BACKSLASH) return "BACKSLASH";
    if (t == ic_token_type::BITWISE_NOT) return "BITWISE_NOT";
    if (t == ic_token_type::BOOL_NOT) return "BOOL_NOT";
    if (t == ic_token_type::CLOSE_BRACKET) return "CLOSE_BRACKET";
    if (t == ic_token_type::CLOSE_CURLY) return "CLOSE_CURLY";
    if (t == ic_token_type::CLOSE_PAREN) return "CLOSE_PAREN";
    if (t == ic_token_type::COLON) return "COLON";
    if (t == ic_token_type::COMMA) return "COMMA";
    if (t == ic_token_type::COMMENT) return "COMMENT";
    if (t == ic_token_type::DEC_OP) return "DEC_OP";
    if (t == ic_token_type::DIV) return "DIV";
    if (t == ic_token_type::DIV_ASSIGN) return "DIV_ASSIGN";
    if (t == ic_token_type::DOT) return "DOT";
    if (t == ic_token_type::ELLIPSIS) return "ELLIPSIS";
    if (t == ic_token_type::ENUMERATION_CONSTANT) return "ENUMERATION_CONSTANT";
    if (t == ic_token_type::EQ) return "EQ";
    if (t == ic_token_type::EQ_OP) return "EQ_OP";
    if (t == ic_token_type::FLOAT_CONSTANT) return "FLOAT_CONSTANT";
    if (t == ic_token_type::GE_OP) return "GE_OP";
    if (t == ic_token_type::GREATER) return "GREATER";
    if (t == ic_token_type::HASH) return "HASH";
    if (t == ic_token_type::HASH_HASH) return "HASH_HASH";
    if (t == ic_token_type::IDENTIFIER) return "IDENTIFIER";
    if (t == ic_token_type::INC_OP) return "INC_OP";
    if (t == ic_token_type::INTEGER_CONSTANT) return "INTEGER_CONSTANT";
    if (t == ic_token_type::LEFT_ASSIGN) return "LEFT_ASSIGN";
    if (t == ic_token_type::LEFT_OP) return "LEFT_OP";
    if (t == ic_token_type::LESS) return "LESS";
    if (t == ic_token_type::LE_OP) return "LE_OP";
    if (t == ic_token_type::MOD) return "MOD";
    if (t == ic_token_type::MOD_ASSIGN) return "MOD_ASSIGN";
    if (t == ic_token_type::MUL) return "MUL";
    if (t == ic_token_type::MULTILINE_COMMENT) return "MULTILINE_COMMENT";
    if (t == ic_token_type::MUL_ASSIGN) return "MUL_ASSIGN";
    if (t == ic_token_type::NEWLINE) return "NEWLINE";
    if (t == ic_token_type::NE_OP) return "NE_OP";
    if (t == ic_token_type::NON_IDENTIFIER) return "NON_IDENTIFIER";
    if (t == ic_token_type::OPEN_BRACKET) return "OPEN_BRACKET";
    if (t == ic_token_type::OPEN_CURLY) return "OPEN_CURLY";
    if (t == ic_token_type::OPEN_PAREN) return "OPEN_PAREN";
    if (t == ic_token_type::OR) return "OR";
    if (t == ic_token_type::OR_ASSIGN) return "OR_ASSIGN";
    if (t == ic_token_type::OR_OP) return "OR_OP";
    if (t == ic_token_type::PP_CONCAT) return "PP_CONCAT";
    if (t == ic_token_type::PP_DEFINE) return "PP_DEFINE";
    if (t == ic_token_type::PP_DEFINED) return "PP_DEFINED";
    if (t == ic_token_type::PP_DUNDER_FILE) return "PP_DUNDER_FILE";
    if (t == ic_token_type::PP_DUNDER_LINE) return "PP_DUNDER_LINE";
    if (t == ic_token_type::PP_DUNDER_VARARGS) return "PP_DUNDER_VARARGS";
    if (t == ic_token_type::PP_ELIF) return "PP_ELIF";
    if (t == ic_token_type::PP_ELSE) return "PP_ELSE";
    if (t == ic_token_type::PP_ENDIF) return "PP_ENDIF";
    if (t == ic_token_type::PP_ERROR) return "PP_ERROR";
    if (t == ic_token_type::PP_IF) return "PP_IF";
    if (t == ic_token_type::PP_IF_DEF) return "PP_IF_DEF";
    if (t == ic_token_type::PP_IF_N_DEF) return "PP_IF_N_DEF";
    if (t == ic_token_type::PP_INCLUDE) return "PP_INCLUDE";
    if (t == ic_token_type::PP_LINE) return "PP_LINE";
    if (t == ic_token_type::PP_PRAGMA) return "PP_PRAGMA";
    if (t == ic_token_type::PP_STRINGIFY) return "PP_STRINGIFY";
    if (t == ic_token_type::PP_UNDEF) return "PP_UNDEF";
    if (t == ic_token_type::PP_WARN) return "PP_WARN";
    if (t == ic_token_type::PTR_OP) return "PTR_OP";
    if (t == ic_token_type::QUESTION) return "QUESTION";
    if (t == ic_token_type::RIGHT_ASSIGN) return "RIGHT_ASSIGN";
    if (t == ic_token_type::RIGHT_OP) return "RIGHT_OP";
    if (t == ic_token_type::SEMICOLON) return "SEMICOLON";
    if (t == ic_token_type::STRING_LITERAL) return "STRING_LITERAL";
    if (t == ic_token_type::SUB) return "SUB";
    if (t == ic_token_type::SUB_ASSIGN) return "SUB_ASSIGN";
    if (t == ic_token_type::TC_EOF) return "TC_EOF";
    if (t == ic_token_type::TYPEDEF_NAME) return "TYPEDEF_NAME";
    if (t == ic_token_type::XOR) return "XOR";
    if (t == ic_token_type::XOR_ASSIGN) return "XOR_ASSIGN";
    if (t == ic_token_type::KEYWORD_ALIGNAS) return "KEYWORD_ALIGNAS";
    if (t == ic_token_type::KEYWORD_ALIGNOF) return "KEYWORD_ALIGNOF";
    if (t == ic_token_type::KEYWORD_ATOMIC) return "KEYWORD_ATOMIC";
    if (t == ic_token_type::KEYWORD_BOOL) return "KEYWORD_BOOL";
    if (t == ic_token_type::KEYWORD_COMPLEX) return "KEYWORD_COMPLEX";
    if (t == ic_token_type::KEYWORD_GENERIC) return "KEYWORD_GENERIC";
    if (t == ic_token_type::KEYWORD_IMAGINARY) return "KEYWORD_IMAGINARY";
    if (t == ic_token_type::KEYWORD_NORETURN) return "KEYWORD_NORETURN";
    if (t == ic_token_type::KEYWORD_STATICASSERT) return "KEYWORD_STATICASSERT";
    if (t == ic_token_type::KEYWORD_THREADLOCAL) return "KEYWORD_THREADLOCAL";
    if (t == ic_token_type::KEYWORD_FUNC) return "KEYWORD_FUNC";
    if (t == ic_token_type::KEYWORD_AUTO) return "KEYWORD_AUTO";
    if (t == ic_token_type::KEYWORD_BREAK) return "KEYWORD_BREAK";
    if (t == ic_token_type::KEYWORD_CASE) return "KEYWORD_CASE";
    if (t == ic_token_type::KEYWORD_CHAR) return "KEYWORD_CHAR";
    if (t == ic_token_type::KEYWORD_CONST) return "KEYWORD_CONST";
    if (t == ic_token_type::KEYWORD_CONTINUE) return "KEYWORD_CONTINUE";
    if (t == ic_token_type::KEYWORD_DEFAULT) return "KEYWORD_DEFAULT";
    if (t == ic_token_type::KEYWORD_DO) return "KEYWORD_DO";
    if (t == ic_token_type::KEYWORD_DOUBLE) return "KEYWORD_DOUBLE";
    if (t == ic_token_type::KEYWORD_ELSE) return "KEYWORD_ELSE";
    if (t == ic_token_type::KEYWORD_ENUM) return "KEYWORD_ENUM";
    if (t == ic_token_type::KEYWORD_EXTERN) return "KEYWORD_EXTERN";
    if (t == ic_token_type::KEYWORD_FLOAT) return "KEYWORD_FLOAT";
    if (t == ic_token_type::KEYWORD_FOR) return "KEYWORD_FOR";
    if (t == ic_token_type::KEYWORD_GOTO) return "KEYWORD_GOTO";
    if (t == ic_token_type::KEYWORD_IF) return "KEYWORD_IF";
    if (t == ic_token_type::KEYWORD_INLINE) return "KEYWORD_INLINE";
    if (t == ic_token_type::KEYWORD_INT) return "KEYWORD_INT";
    if (t == ic_token_type::KEYWORD_LONG) return "KEYWORD_LONG";
    if (t == ic_token_type::KEYWORD_REGISTER) return "KEYWORD_REGISTER";
    if (t == ic_token_type::KEYWORD_RESTRICT) return "KEYWORD_RESTRICT";
    if (t == ic_token_type::KEYWORD_RETURN) return "KEYWORD_RETURN";
    if (t == ic_token_type::KEYWORD_SHORT) return "KEYWORD_SHORT";
    if (t == ic_token_type::KEYWORD_SIGNED) return "KEYWORD_SIGNED";
    if (t == ic_token_type::KEYWORD_SIZEOF) return "KEYWORD_SIZEOF";
    if (t == ic_token_type::KEYWORD_STATIC) return "KEYWORD_STATIC";
    if (t == ic_token_type::KEYWORD_STRUCT) return "KEYWORD_STRUCT";
    if (t == ic_token_type::KEYWORD_SWITCH) return "KEYWORD_SWITCH";
    if (t == ic_token_type::KEYWORD_TYPEDEF) return "KEYWORD_TYPEDEF";
    if (t == ic_token_type::KEYWORD_UNION) return "KEYWORD_UNION";
    if (t == ic_token_type::KEYWORD_UNSIGNED) return "KEYWORD_UNSIGNED";
    if (t == ic_token_type::KEYWORD_VOID) return "KEYWORD_VOID";
    if (t == ic_token_type::KEYWORD_VOLATILE) return "KEYWORD_VOLATILE";
    if (t == ic_token_type::KEYWORD_WHILE) return "KEYWORD_WHILE";
    return "TK_UNKNOWN_TOKEN_DETECTED";
  }
  static inline ic_token_type ic_str_to_token(const std::string &t) {
    if (t == "ADD") return ic_token_type::ADD;
    if (t == "ADD_ASSIGN") return ic_token_type::ADD_ASSIGN;
    if (t == "AMPERSAND") return ic_token_type::AMPERSAND;
    if (t == "AND_ASSIGN") return ic_token_type::AND_ASSIGN;
    if (t == "AND_OP") return ic_token_type::AND_OP;
    if (t == "BACKSLASH") return ic_token_type::BACKSLASH;
    if (t == "BITWISE_NOT") return ic_token_type::BITWISE_NOT;
    if (t == "BOOL_NOT") return ic_token_type::BOOL_NOT;
    if (t == "CLOSE_BRACKET") return ic_token_type::CLOSE_BRACKET;
    if (t == "CLOSE_CURLY") return ic_token_type::CLOSE_CURLY;
    if (t == "CLOSE_PAREN") return ic_token_type::CLOSE_PAREN;
    if (t == "COLON") return ic_token_type::COLON;
    if (t == "COMMA") return ic_token_type::COMMA;
    if (t == "COMMENT") return ic_token_type::COMMENT;
    if (t == "DEC_OP") return ic_token_type::DEC_OP;
    if (t == "DIV") return ic_token_type::DIV;
    if (t == "DIV_ASSIGN") return ic_token_type::DIV_ASSIGN;
    if (t == "DOT") return ic_token_type::DOT;
    if (t == "ELLIPSIS") return ic_token_type::ELLIPSIS;
    if (t == "ENUMERATION_CONSTANT") return ic_token_type::ENUMERATION_CONSTANT;
    if (t == "EQ") return ic_token_type::EQ;
    if (t == "EQ_OP") return ic_token_type::EQ_OP;
    if (t == "FLOAT_CONSTANT") return ic_token_type::FLOAT_CONSTANT;
    if (t == "GE_OP") return ic_token_type::GE_OP;
    if (t == "GREATER") return ic_token_type::GREATER;
    if (t == "HASH") return ic_token_type::HASH;
    if (t == "HASH_HASH") return ic_token_type::HASH_HASH;
    if (t == "IDENTIFIER") return ic_token_type::IDENTIFIER;
    if (t == "INC_OP") return ic_token_type::INC_OP;
    if (t == "INTEGER_CONSTANT") return ic_token_type::INTEGER_CONSTANT;
    if (t == "LEFT_ASSIGN") return ic_token_type::LEFT_ASSIGN;
    if (t == "LEFT_OP") return ic_token_type::LEFT_OP;
    if (t == "LESS") return ic_token_type::LESS;
    if (t == "LE_OP") return ic_token_type::LE_OP;
    if (t == "MOD") return ic_token_type::MOD;
    if (t == "MOD_ASSIGN") return ic_token_type::MOD_ASSIGN;
    if (t == "MUL") return ic_token_type::MUL;
    if (t == "MULTILINE_COMMENT") return ic_token_type::MULTILINE_COMMENT;
    if (t == "MUL_ASSIGN") return ic_token_type::MUL_ASSIGN;
    if (t == "NEWLINE") return ic_token_type::NEWLINE;
    if (t == "NE_OP") return ic_token_type::NE_OP;
    if (t == "NON_IDENTIFIER") return ic_token_type::NON_IDENTIFIER;
    if (t == "OPEN_BRACKET") return ic_token_type::OPEN_BRACKET;
    if (t == "OPEN_CURLY") return ic_token_type::OPEN_CURLY;
    if (t == "OPEN_PAREN") return ic_token_type::OPEN_PAREN;
    if (t == "OR") return ic_token_type::OR;
    if (t == "OR_ASSIGN") return ic_token_type::OR_ASSIGN;
    if (t == "OR_OP") return ic_token_type::OR_OP;
    if (t == "PP_CONCAT") return ic_token_type::PP_CONCAT;
    if (t == "PP_DEFINE") return ic_token_type::PP_DEFINE;
    if (t == "PP_DEFINED") return ic_token_type::PP_DEFINED;
    if (t == "PP_DUNDER_FILE") return ic_token_type::PP_DUNDER_FILE;
    if (t == "PP_DUNDER_LINE") return ic_token_type::PP_DUNDER_LINE;
    if (t == "PP_DUNDER_VARARGS") return ic_token_type::PP_DUNDER_VARARGS;
    if (t == "PP_ELIF") return ic_token_type::PP_ELIF;
    if (t == "PP_ELSE") return ic_token_type::PP_ELSE;
    if (t == "PP_ENDIF") return ic_token_type::PP_ENDIF;
    if (t == "PP_ERROR") return ic_token_type::PP_ERROR;
    if (t == "PP_IF") return ic_token_type::PP_IF;
    if (t == "PP_IF_DEF") return ic_token_type::PP_IF_DEF;
    if (t == "PP_IF_N_DEF") return ic_token_type::PP_IF_N_DEF;
    if (t == "PP_INCLUDE") return ic_token_type::PP_INCLUDE;
    if (t == "PP_LINE") return ic_token_type::PP_LINE;
    if (t == "PP_PRAGMA") return ic_token_type::PP_PRAGMA;
    if (t == "PP_STRINGIFY") return ic_token_type::PP_STRINGIFY;
    if (t == "PP_UNDEF") return ic_token_type::PP_UNDEF;
    if (t == "PP_WARN") return ic_token_type::PP_WARN;
    if (t == "PTR_OP") return ic_token_type::PTR_OP;
    if (t == "QUESTION") return ic_token_type::QUESTION;
    if (t == "RIGHT_ASSIGN") return ic_token_type::RIGHT_ASSIGN;
    if (t == "RIGHT_OP") return ic_token_type::RIGHT_OP;
    if (t == "SEMICOLON") return ic_token_type::SEMICOLON;
    if (t == "STRING_LITERAL") return ic_token_type::STRING_LITERAL;
    if (t == "SUB") return ic_token_type::SUB;
    if (t == "SUB_ASSIGN") return ic_token_type::SUB_ASSIGN;
    if (t == "TC_EOF") return ic_token_type::TC_EOF;
    if (t == "TYPEDEF_NAME") return ic_token_type::TYPEDEF_NAME;
    if (t == "XOR") return ic_token_type::XOR;
    if (t == "XOR_ASSIGN") return ic_token_type::XOR_ASSIGN;
    if (t == "KEYWORD_ALIGNAS") return ic_token_type::KEYWORD_ALIGNAS;
    if (t == "KEYWORD_ALIGNOF") return ic_token_type::KEYWORD_ALIGNOF;
    if (t == "KEYWORD_ATOMIC") return ic_token_type::KEYWORD_ATOMIC;
    if (t == "KEYWORD_BOOL") return ic_token_type::KEYWORD_BOOL;
    if (t == "KEYWORD_COMPLEX") return ic_token_type::KEYWORD_COMPLEX;
    if (t == "KEYWORD_GENERIC") return ic_token_type::KEYWORD_GENERIC;
    if (t == "KEYWORD_IMAGINARY") return ic_token_type::KEYWORD_IMAGINARY;
    if (t == "KEYWORD_NORETURN") return ic_token_type::KEYWORD_NORETURN;
    if (t == "KEYWORD_STATICASSERT") return ic_token_type::KEYWORD_STATICASSERT;
    if (t == "KEYWORD_THREADLOCAL") return ic_token_type::KEYWORD_THREADLOCAL;
    if (t == "KEYWORD_FUNC") return ic_token_type::KEYWORD_FUNC;
    if (t == "KEYWORD_AUTO") return ic_token_type::KEYWORD_AUTO;
    if (t == "KEYWORD_BREAK") return ic_token_type::KEYWORD_BREAK;
    if (t == "KEYWORD_CASE") return ic_token_type::KEYWORD_CASE;
    if (t == "KEYWORD_CHAR") return ic_token_type::KEYWORD_CHAR;
    if (t == "KEYWORD_CONST") return ic_token_type::KEYWORD_CONST;
    if (t == "KEYWORD_CONTINUE") return ic_token_type::KEYWORD_CONTINUE;
    if (t == "KEYWORD_DEFAULT") return ic_token_type::KEYWORD_DEFAULT;
    if (t == "KEYWORD_DO") return ic_token_type::KEYWORD_DO;
    if (t == "KEYWORD_DOUBLE") return ic_token_type::KEYWORD_DOUBLE;
    if (t == "KEYWORD_ELSE") return ic_token_type::KEYWORD_ELSE;
    if (t == "KEYWORD_ENUM") return ic_token_type::KEYWORD_ENUM;
    if (t == "KEYWORD_EXTERN") return ic_token_type::KEYWORD_EXTERN;
    if (t == "KEYWORD_FLOAT") return ic_token_type::KEYWORD_FLOAT;
    if (t == "KEYWORD_FOR") return ic_token_type::KEYWORD_FOR;
    if (t == "KEYWORD_GOTO") return ic_token_type::KEYWORD_GOTO;
    if (t == "KEYWORD_IF") return ic_token_type::KEYWORD_IF;
    if (t == "KEYWORD_INLINE") return ic_token_type::KEYWORD_INLINE;
    if (t == "KEYWORD_INT") return ic_token_type::KEYWORD_INT;
    if (t == "KEYWORD_LONG") return ic_token_type::KEYWORD_LONG;
    if (t == "KEYWORD_REGISTER") return ic_token_type::KEYWORD_REGISTER;
    if (t == "KEYWORD_RESTRICT") return ic_token_type::KEYWORD_RESTRICT;
    if (t == "KEYWORD_RETURN") return ic_token_type::KEYWORD_RETURN;
    if (t == "KEYWORD_SHORT") return ic_token_type::KEYWORD_SHORT;
    if (t == "KEYWORD_SIGNED") return ic_token_type::KEYWORD_SIGNED;
    if (t == "KEYWORD_SIZEOF") return ic_token_type::KEYWORD_SIZEOF;
    if (t == "KEYWORD_STATIC") return ic_token_type::KEYWORD_STATIC;
    if (t == "KEYWORD_STRUCT") return ic_token_type::KEYWORD_STRUCT;
    if (t == "KEYWORD_SWITCH") return ic_token_type::KEYWORD_SWITCH;
    if (t == "KEYWORD_TYPEDEF") return ic_token_type::KEYWORD_TYPEDEF;
    if (t == "KEYWORD_UNION") return ic_token_type::KEYWORD_UNION;
    if (t == "KEYWORD_UNSIGNED") return ic_token_type::KEYWORD_UNSIGNED;
    if (t == "KEYWORD_VOID") return ic_token_type::KEYWORD_VOID;
    if (t == "KEYWORD_VOLATILE") return ic_token_type::KEYWORD_VOLATILE;
    if (t == "KEYWORD_WHILE") return ic_token_type::KEYWORD_WHILE;
    return ic_token_type::TK_UNKNOWN_TOKEN_DETECTED;
  }
  static inline ic_token_type ic_str_to_keyword(const std::string &t) {
    if (t == "_Alignas") return ic_token_type::KEYWORD_ALIGNAS;
    if (t == "_Alignof") return ic_token_type::KEYWORD_ALIGNOF;
    if (t == "_Atomic") return ic_token_type::KEYWORD_ATOMIC;
    if (t == "_Bool") return ic_token_type::KEYWORD_BOOL;
    if (t == "_Complex") return ic_token_type::KEYWORD_COMPLEX;
    if (t == "_Generic") return ic_token_type::KEYWORD_GENERIC;
    if (t == "_Imaginary") return ic_token_type::KEYWORD_IMAGINARY;
    if (t == "_Noreturn") return ic_token_type::KEYWORD_NORETURN;
    if (t == "_Static_assert") return ic_token_type::KEYWORD_STATICASSERT;
    if (t == "_Thread_local") return ic_token_type::KEYWORD_THREADLOCAL;
    if (t == "__func__") return ic_token_type::KEYWORD_FUNC;
    if (t == "auto") return ic_token_type::KEYWORD_AUTO;
    if (t == "break") return ic_token_type::KEYWORD_BREAK;
    if (t == "case") return ic_token_type::KEYWORD_CASE;
    if (t == "char") return ic_token_type::KEYWORD_CHAR;
    if (t == "const") return ic_token_type::KEYWORD_CONST;
    if (t == "continue") return ic_token_type::KEYWORD_CONTINUE;
    if (t == "default") return ic_token_type::KEYWORD_DEFAULT;
    if (t == "do") return ic_token_type::KEYWORD_DO;
    if (t == "double") return ic_token_type::KEYWORD_DOUBLE;
    if (t == "else") return ic_token_type::KEYWORD_ELSE;
    if (t == "enum") return ic_token_type::KEYWORD_ENUM;
    if (t == "extern") return ic_token_type::KEYWORD_EXTERN;
    if (t == "float") return ic_token_type::KEYWORD_FLOAT;
    if (t == "for") return ic_token_type::KEYWORD_FOR;
    if (t == "goto") return ic_token_type::KEYWORD_GOTO;
    if (t == "if") return ic_token_type::KEYWORD_IF;
    if (t == "inline") return ic_token_type::KEYWORD_INLINE;
    if (t == "int") return ic_token_type::KEYWORD_INT;
    if (t == "long") return ic_token_type::KEYWORD_LONG;
    if (t == "register") return ic_token_type::KEYWORD_REGISTER;
    if (t == "restrict") return ic_token_type::KEYWORD_RESTRICT;
    if (t == "return") return ic_token_type::KEYWORD_RETURN;
    if (t == "short") return ic_token_type::KEYWORD_SHORT;
    if (t == "signed") return ic_token_type::KEYWORD_SIGNED;
    if (t == "sizeof") return ic_token_type::KEYWORD_SIZEOF;
    if (t == "static") return ic_token_type::KEYWORD_STATIC;
    if (t == "struct") return ic_token_type::KEYWORD_STRUCT;
    if (t == "switch") return ic_token_type::KEYWORD_SWITCH;
    if (t == "typedef") return ic_token_type::KEYWORD_TYPEDEF;
    if (t == "union") return ic_token_type::KEYWORD_UNION;
    if (t == "unsigned") return ic_token_type::KEYWORD_UNSIGNED;
    if (t == "void") return ic_token_type::KEYWORD_VOID;
    if (t == "volatile") return ic_token_type::KEYWORD_VOLATILE;
    if (t == "while") return ic_token_type::KEYWORD_WHILE;
    return ic_token_type::TK_UNKNOWN_TOKEN_DETECTED;
  }
  enum class ic_integer_type {
    UNUSED_DEFAULT,
    I_I,
    I_L,
    I_LL,
    I_U,
    I_UL,
    I_ULL,
    I_NOTHING,
    TK_UNKNOWN_TOKEN_DETECTED
  };
  static inline std::string ic_integer_type_to_str(const ic_integer_type &t) {
    if (t == ic_integer_type::UNUSED_DEFAULT) return "UNUSED_DEFAULT";
    if (t == ic_integer_type::I_I) return "I_I";
    if (t == ic_integer_type::I_L) return "I_L";
    if (t == ic_integer_type::I_LL) return "I_LL";
    if (t == ic_integer_type::I_U) return "I_U";
    if (t == ic_integer_type::I_UL) return "I_UL";
    if (t == ic_integer_type::I_ULL) return "I_ULL";
    if (t == ic_integer_type::I_NOTHING) return "I_NOTHING";
    return "TK_UNKNOWN_TOKEN_DETECTED";
  }
  static inline ic_integer_type str_to_ic_integer_type(const std::string &t) {
    if (t == "UNUSED_DEFAULT") return ic_integer_type::UNUSED_DEFAULT;
    if (t == "I_I") return ic_integer_type::I_I;
    if (t == "I_L") return ic_integer_type::I_L;
    if (t == "I_LL") return ic_integer_type::I_LL;
    if (t == "I_U") return ic_integer_type::I_U;
    if (t == "I_UL") return ic_integer_type::I_UL;
    if (t == "I_ULL") return ic_integer_type::I_ULL;
    if (t == "I_NOTHING") return ic_integer_type::I_NOTHING;
    return ic_integer_type::TK_UNKNOWN_TOKEN_DETECTED;
  }
  enum class ic_integer_base {
    UNUSED_DEFAULT,
    I_HEX,
    I_DEC,
    I_OCT,
    I_BIN,
    I_SINGLE_QUOTED,
    I_SINGLE_QUOTED_L,
    TK_UNKNOWN_TOKEN_DETECTED
  };
  static inline std::string ic_integer_base_to_str(const ic_integer_base &t) {
    if (t == ic_integer_base::UNUSED_DEFAULT) return "UNUSED_DEFAULT";
    if (t == ic_integer_base::I_HEX) return "I_HEX";
    if (t == ic_integer_base::I_DEC) return "I_DEC";
    if (t == ic_integer_base::I_OCT) return "I_OCT";
    if (t == ic_integer_base::I_BIN) return "I_BIN";
    if (t == ic_integer_base::I_SINGLE_QUOTED) return "I_SINGLE_QUOTED";
    if (t == ic_integer_base::I_SINGLE_QUOTED_L) return "I_SINGLE_QUOTED_L";
    return "TK_UNKNOWN_TOKEN_DETECTED";
  }
  static inline ic_integer_base str_to_ic_integer_base(const std::string &t) {
    if (t == "UNUSED_DEFAULT") return ic_integer_base::UNUSED_DEFAULT;
    if (t == "I_HEX") return ic_integer_base::I_HEX;
    if (t == "I_DEC") return ic_integer_base::I_DEC;
    if (t == "I_OCT") return ic_integer_base::I_OCT;
    if (t == "I_BIN") return ic_integer_base::I_BIN;
    if (t == "I_SINGLE_QUOTED") return ic_integer_base::I_SINGLE_QUOTED;
    if (t == "I_SINGLE_QUOTED_L") return ic_integer_base::I_SINGLE_QUOTED_L;
    return ic_integer_base::TK_UNKNOWN_TOKEN_DETECTED;
  }
  enum class ic_string_literal_type {
    UNUSED_DEFAULT,
    S_STRING,
    S_STRING_L,
    TK_UNKNOWN_TOKEN_DETECTED
  };
  static inline std::string
  ic_string_literal_type_to_str(const ic_string_literal_type &t) {
    if (t == ic_string_literal_type::UNUSED_DEFAULT) return "UNUSED_DEFAULT";
    if (t == ic_string_literal_type::S_STRING) return "S_STRING";
    if (t == ic_string_literal_type::S_STRING_L) return "S_STRING_L";
    return "TK_UNKNOWN_TOKEN_DETECTED";
  }
  static inline ic_string_literal_type
  str_to_ic_string_literal_type(const std::string &t) {
    if (t == "UNUSED_DEFAULT") return ic_string_literal_type::UNUSED_DEFAULT;
    if (t == "S_STRING") return ic_string_literal_type::S_STRING;
    if (t == "S_STRING_L") return ic_string_literal_type::S_STRING_L;
    return ic_string_literal_type::TK_UNKNOWN_TOKEN_DETECTED;
  }
  enum class ic_float_type {
    UNUSED_DEFAULT,
    F_FLOAT,
    F_DOUBLE,
    F_LONG_DOUBLE,
    TK_UNKNOWN_TOKEN_DETECTED
  };
  static inline std::string ic_float_type_to_str(const ic_float_type &t) {
    if (t == ic_float_type::UNUSED_DEFAULT) return "UNUSED_DEFAULT";
    if (t == ic_float_type::F_FLOAT) return "F_FLOAT";
    if (t == ic_float_type::F_DOUBLE) return "F_DOUBLE";
    if (t == ic_float_type::F_LONG_DOUBLE) return "F_LONG_DOUBLE";
    return "TK_UNKNOWN_TOKEN_DETECTED";
  }
  static inline ic_float_type str_to_ic_float_type(const std::string &t) {
    if (t == "UNUSED_DEFAULT") return ic_float_type::UNUSED_DEFAULT;
    if (t == "F_FLOAT") return ic_float_type::F_FLOAT;
    if (t == "F_DOUBLE") return ic_float_type::F_DOUBLE;
    if (t == "F_LONG_DOUBLE") return ic_float_type::F_LONG_DOUBLE;
    return ic_float_type::TK_UNKNOWN_TOKEN_DETECTED;
  }
  /**
 * Single token
 */
  struct ic_token {
    std::string file_;// filename
    int line_;        // line in file
    int pos_;         // position in line
    std::string token_;
    ic_token_type type_;// type of the token
    std::string original_;
    ic_integer_type itype_{ic_integer_type::UNUSED_DEFAULT};
    ic_integer_base ibase_{ic_integer_base::UNUSED_DEFAULT};
    ic_string_literal_type stype_{ic_string_literal_type::UNUSED_DEFAULT};
    ic_float_type ftype_{ic_float_type::UNUSED_DEFAULT};
  };
  /**
 * Content of an error message
 */
  struct ic_parsing_error : std::exception {
    std::string message_;// content of the line this error occurred
    ic_token tok_;
    [[maybe_unused]] bool token_set_{};
    ic_parsing_error(std::string message, ic_token *at);
    ic_parsing_error(std::string message, std::string file, int line, int pos);
  };
}// namespace yaksha
#endif
